package com.malou.server.seguridad.menu;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.ibatis.sqlmap.client.SqlMapClient;
import com.malou.client.seguridad.menu.MenuOpciones;
import com.malou.server.base.Conexion;
import com.malou.server.base.acl.My_Acl;
import com.malou.server.base.acl.My_Acl_Role;

public class Menus {
	
	private static SqlMapClient sqlMap = null;
	public static Integer guardado_id;
	public static Integer errorTipo = 0;
	
	public static Integer usuario_id;
	public static Integer tipo;
	private static My_Acl acl;
	
	/*@SuppressWarnings("unchecked")
	public static MenuOpciones getTreeMenu(MenuOpciones menu){
		Conexion xon = new Conexion();
        SqlMapClient sqlMap = null;
        
        sqlMap = xon.getSqlMap();
        List<MenuOpciones> menus = null;
		try {
			if (menu == null)
				menus = sqlMap.queryForList("getMenusRaiz", null);				
			else
				menus = sqlMap.queryForList("getMenusHijos", menu);				
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		MenuOpciones root = new MenuOpciones();
		for (int i = 0; i < menus.size(); i++) {
			MenuOpciones mnu = (MenuOpciones) menus.get(i);
			//mnu.add(new MenuOpciones(200,"Prueba","prueba",mnu.getId(),1,false));
			root.add(mnu);
	    }
	    return root;
	}*/
	
	public static boolean save(MenuOpciones mnu){
		boolean retorno = true;	   
		
		sqlMap = Conexion.getSqlMap();
		try {		
			if(validaDescripcionMenu(mnu)){	
				if(mnu.getId() != null)
					sqlMap.update("updateMenu", mnu);
				else{
					sqlMap.startTransaction();
					if(mnu.getParent_id() != null){
						if(mnu.getTipo()==1)
							sqlMap.update("updateMenuPadre", mnu);
						else if(mnu.getTipo()==2)
							sqlMap.update("updateMenuPadreOperacion", mnu);
					}
					
					sqlMap.insert("insertMenu", mnu);
					sqlMap.commitTransaction();				
				}
			}else
				retorno = false;
			
		} catch (SQLException e) {
			retorno = false;
			e.printStackTrace();			
		}
		
		try {
			sqlMap.endTransaction();
		} catch (SQLException e1) {				
			e1.printStackTrace();
		}
		
		return retorno;
	}
	
	private static boolean validaDescripcionMenu(MenuOpciones mnu){
		boolean retorno = true;		
		
		try {
			if(mnu.getId() == null)
				mnu.setId(0);
			
			Integer cant = (Integer)sqlMap.queryForObject("validaDescripcionMenu", mnu);
			
			if(mnu.getId() == 0)
				mnu.setId(null);
			
			if(cant != 0){
	            retorno = false;
	            errorTipo = 1;//Este menu ya existe en el nivel	            
	        }else{
	        	if(mnu.getId() == null)
					mnu.setId(0);
				
				cant = (Integer)sqlMap.queryForObject("validaParametroMenu", mnu);
				
				if(mnu.getId() == 0)
					mnu.setId(null);
				
				if(cant != 0){				
					retorno = false;
					if(mnu.getTipo() == 1)
						errorTipo = 2;//Este parametro de menu ya existe
					if(mnu.getTipo() == 2)
						errorTipo = 3;//Este parametro de operacion ya existe en este nivel
				}
				
	        }
		} catch (SQLException e) {
			retorno = false;
			e.printStackTrace();			
		}
		
		return retorno;
	}
	
	public static boolean delete(Integer id){
		boolean retorno = true;    
		
		sqlMap = Conexion.getSqlMap();		
		
		try {
			sqlMap.startTransaction();
			MenuOpciones mnu = (MenuOpciones)sqlMap.queryForObject("getMenu", id);
			Integer parent_id = mnu.getParent_id();
			if(parent_id != null){
				Integer cant = (Integer)sqlMap.queryForObject("getCountMenusHijos", parent_id);;
				
				if(cant == 1)
					sqlMap.update("updateMenuSinHijos", parent_id);
			}
			if(id != null)
				sqlMap.delete("deleteMenu", id);
			else
				retorno = false;
			sqlMap.commitTransaction();
		} catch (SQLException e) {
			retorno = false;
			e.printStackTrace();			
		}
		
		try {
			sqlMap.endTransaction();
		} catch (SQLException e1) {				
			e1.printStackTrace();
		}
		return retorno;
	}
	
	@SuppressWarnings("unchecked")
	public static List<MenuOpciones> getTreeMenu(){
		     
		acl = new My_Acl();
        sqlMap = Conexion.getSqlMap();        
        
        List<MenuOpciones> menus = null;
        
        if(tipo!= null){
        	addResources();
        	if (tipo == 1){
        		addRolPadre(usuario_id);
        		acl.beforeAllow();
        		addPermisosRoles();
        	}else if(tipo == 2){
        		acl.user_id = usuario_id;
            	acl.parents_id = getRoles(usuario_id);
            	
            	acl.beforeAllow();
            	addPermisosRoles();
        	}
        	
        }
        
		try {
			MenuOpciones op = new  MenuOpciones();			
			op.setUsuario_id(usuario_id);
			op.setUsuariotipo(tipo);
			if(tipo == null){
				menus = sqlMap.queryForList("getMenus", op);
			}else{						
				menus = sqlMap.queryForList("getMenusPermiso", op);
			}
							
		} catch (SQLException e) {
			e.printStackTrace();
		}
		Integer resource_id;
		for (int i = 0; i < menus.size(); i++) {
			MenuOpciones mnu = (MenuOpciones) menus.get(i);
			//acl.add(mnu.getId());
			if(tipo!= null)
			if(mnu.getPermitido()==null){
				resource_id = mnu.getId();
				if(tipo == 1){
					if(acl.isAllowed(usuario_id, resource_id))
						mnu.setPermitido(true);
				}else if(tipo==2){
					if(acl.isAllowed(resource_id))
						mnu.setPermitido(true);
				}				
			}
			if(mnu.getHaschildren() != null){				
				getMenuHijo(mnu);
			}
	    }	
				
		
	    return menus;
	}
	
	@SuppressWarnings("unchecked")
	private static void getMenuHijo(MenuOpciones menu){
		
		List<MenuOpciones> menus = null;
		
		try {
			menu.setUsuario_id(usuario_id);
			menu.setUsuariotipo(tipo);
			if(tipo == null)
				menus = sqlMap.queryForList("getMenus", menu);
			else				
				menus = sqlMap.queryForList("getMenusPermiso", menu);
			Integer resource_id;
			for (int i = 0; i < menus.size(); i++) {
				MenuOpciones mnu = (MenuOpciones) menus.get(i);
				//acl.add(mnu.getId());
				if(tipo!= null)
				if(mnu.getPermitido()==null){
					resource_id = mnu.getId();
					if(tipo == 1){
						if(acl.isAllowed(usuario_id, resource_id))
							mnu.setPermitido(true);
					}else if(tipo==2){
						if(acl.isAllowed(resource_id))
							mnu.setPermitido(true);
					}					
				}
				menu.add(mnu);
				
				if(mnu.getHaschildren() != null)
					getMenuHijo(mnu);					
		    }
		} catch (SQLException e) {
			e.printStackTrace();
		}			
		
	}
	
	@SuppressWarnings("rawtypes")
	private static List<Integer> getRoles(Integer usuario_id){		
		List data = null;
		List<Integer> roles_id = new ArrayList<Integer>();
		Integer parent_id;
		Integer rol_id;
		try {
			data = sqlMap.queryForList("getRolesUsuarioId", usuario_id);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		for (int i = 0; i < data.size(); i++) {
			Map map = (HashMap)data.get(i);
			rol_id = Integer.parseInt(map.get("rol_id").toString());
			roles_id.add(rol_id);
			if(map.get("parent_id") != null){
				parent_id = Integer.parseInt(map.get("parent_id").toString());
				acl.addRole(new My_Acl_Role(rol_id, parent_id));
				addRolPadre(parent_id);
			}else
				acl.addRole(new My_Acl_Role(rol_id));
		}
		
		return roles_id;
	}
	
	@SuppressWarnings("rawtypes")
	private static void addRolPadre(Integer rol_id){		
		List data = null;
		Integer parent_id;		
		try {
			data = sqlMap.queryForList("getRolDetalle", rol_id);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		Map map = (HashMap)data.get(0);
		if(map.get("parent_id") != null){
			parent_id = Integer.parseInt(map.get("parent_id").toString());
			acl.addRole(new My_Acl_Role(rol_id, parent_id));
			addRolPadre(parent_id);
		}else
			acl.addRole(new My_Acl_Role(rol_id));
	}
	
	@SuppressWarnings("rawtypes")
	private static void addPermisosRoles(){
		List data = null;
		List<Integer> roles_id = acl.getAllRoles();
		Boolean permitido;
		Integer menu_id;
		try {
			
			for(Integer rol_id: roles_id){
				data = sqlMap.queryForList("getPermisosRol", rol_id);
				for(int i = 0; i < data.size(); i++){
					Map map = (HashMap)data.get(i);
					permitido = Boolean.parseBoolean(map.get("permitido").toString());
					menu_id = Integer.parseInt(map.get("menu_id").toString());
					if(permitido)
						acl.allow(rol_id, menu_id);
					else
						acl.deny(rol_id, menu_id);
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}		
	}
	

	@SuppressWarnings("rawtypes")
	private static void addResources(){
		List data = null;
		Integer resource_id;
		try {
			data = sqlMap.queryForList("getAllMenus", null);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		for(int i = 0; i < data.size(); i++){
			Map map = (HashMap)data.get(i);
			resource_id = Integer.parseInt(map.get("id").toString());
			acl.add(resource_id);
		}		
	}
	
	public static boolean savePermisos(List<Integer> updateToPermited, List<Integer> insertToPermited, List<Integer> updateIfExistElseInsertToNoPermited){
		boolean retorno = true;
		
		Map<String,Integer> m;
		Integer cant;
		
		sqlMap = Conexion.getSqlMap();
		try {
			sqlMap.startTransaction();
			//tipo 1: rol
			if(tipo == 1){
				m = new HashMap<String,Integer>(2);
				for(Integer menu_id: updateToPermited){
					
					m.put("usuario_id", usuario_id);
					m.put("menu_id", menu_id);
					sqlMap.update("updateToPermitedRol", m);
				}
				m = new HashMap<String,Integer>(2);
				for(Integer menu_id: insertToPermited){
					m.put("usuario_id", usuario_id);
					m.put("menu_id", menu_id);
					sqlMap.insert("insertToPermitedRol", m);
				}
				m = new HashMap<String,Integer>(2);
				for(Integer menu_id: updateIfExistElseInsertToNoPermited){
					m.put("usuario_id", usuario_id);
					m.put("menu_id", menu_id);
					cant = (Integer)sqlMap.queryForObject("getCountMenusRoles", m);
					if(cant==0)
						sqlMap.insert("insertToNoPermitedRol", m);
					else
						sqlMap.update("updateToNoPermitedRol", m);
				}
			}else if(tipo == 2){ //tipo 2: usuario
				m = new HashMap<String,Integer>(2);
				for(Integer menu_id: updateToPermited){
					m.put("usuario_id", usuario_id);
					m.put("menu_id", menu_id);
					sqlMap.update("updateToPermitedUser", m);
				}
				m = new HashMap<String,Integer>(2);
				for(Integer menu_id: insertToPermited){
					m.put("usuario_id", usuario_id);
					m.put("menu_id", menu_id);
					sqlMap.insert("insertToPermitedUser", m);
				}
				m = new HashMap<String,Integer>(2);
				for(Integer menu_id: updateIfExistElseInsertToNoPermited){
					m.put("usuario_id", usuario_id);
					m.put("menu_id", menu_id);
					cant = (Integer)sqlMap.queryForObject("getCountMenusUsers", m);
					if(cant==0)
						sqlMap.insert("insertToNoPermitedUser", m);
					else
						sqlMap.update("updateToNoPermitedUser", m);
				}
			}
			sqlMap.commitTransaction();
		} catch (SQLException e) {
			retorno = false;
			e.printStackTrace();			
		}
		
		try {
			sqlMap.endTransaction();
		} catch (SQLException e1) {				
			e1.printStackTrace();
		}
		
		return retorno;
	}
	
	@SuppressWarnings("unchecked")
	public static List<MenuOpciones> getTreeMenuPermitidos(){		     
		acl = new My_Acl();
        sqlMap = Conexion.getSqlMap();        
        
        List<MenuOpciones> menus = null;        
        
        addResources();
        	
		acl.user_id = usuario_id;
    	acl.parents_id = getRoles(usuario_id);
    	
    	acl.beforeAllow();
    	addPermisosRoles();        
        
		try {
			MenuOpciones op = new  MenuOpciones();			
			op.setUsuario_id(usuario_id);			
								
			menus = sqlMap.queryForList("getMenusPermisoUsuario", op);
			
							
		} catch (SQLException e) {
			e.printStackTrace();
		}
		Integer resource_id;
		
		for (Iterator<MenuOpciones> iter = menus.iterator(); iter.hasNext();) {
			MenuOpciones mnu = iter.next();
			if(mnu.getPermitido()==null){
				resource_id = mnu.getId();
				
				if(acl.isAllowed(resource_id)){
					if(mnu.getHaschildren() != null){				
						getMenuHijoPermitido(mnu);
					}
				}					
				else{
					iter.remove();					
				}
								
			}else if(mnu.getPermitido()){
				if(mnu.getHaschildren() != null){				
					getMenuHijoPermitido(mnu);
				}				
			}else{
				iter.remove();
			}
				      
	    }					
		
	    return menus;
	}
	
	@SuppressWarnings("unchecked")
	private static void getMenuHijoPermitido(MenuOpciones menu){
		
		List<MenuOpciones> menus = null;
		
		try {
			menu.setUsuario_id(usuario_id);						
			menus = sqlMap.queryForList("getMenusPermisoUsuario", menu);
			Integer resource_id;			
			
			for (int i = 0; i < menus.size(); i++) {
				MenuOpciones mnu = (MenuOpciones) menus.get(i);
				
				if(mnu.getPermitido()==null){
					resource_id = mnu.getId();
					
					if(acl.isAllowed(resource_id)){
						if(mnu.getTipo()==1)
							menu.add(mnu);
						else if(mnu.getTipo()==2){
							if(menu.permisos == null){
								menu.permisos = new ArrayList<String>();
							}
							menu.permisos.add(mnu.getParametro());
							menu.setHaschildren(null);
						}
					}
										
				}else if(mnu.getPermitido()){
					if(mnu.getTipo()==1)
						menu.add(mnu);
					else if(mnu.getTipo()==2){
						if(menu.permisos == null){
							menu.permisos = new ArrayList<String>();
						}
						menu.permisos.add(mnu.getParametro());
						menu.setHaschildren(null);
					}
					
					if(mnu.getHaschildren() != null)
						getMenuHijoPermitido(mnu);					
				}
									
		    }
		} catch (SQLException e) {
			e.printStackTrace();
		}			
		
	}
	
	@SuppressWarnings("unchecked")
	public static List<MenuOpciones> getTreeMenuAdmin(){		       
		
        sqlMap = Conexion.getSqlMap();        
        
        List<MenuOpciones> menus = null;   	
        
		try {
											
			menus = sqlMap.queryForList("getMenusRaiz", null);			
							
		} catch (SQLException e) {
			e.printStackTrace();
		}
				
		for (Iterator<MenuOpciones> iter = menus.iterator(); iter.hasNext();) {
			MenuOpciones mnu = iter.next();
			
			if(mnu.getHaschildren() != null){				
				getMenuHijoAdmin(mnu);
			}	      
	    }					
		
	    return menus;
	}
	
	@SuppressWarnings("unchecked")
	private static void getMenuHijoAdmin(MenuOpciones menu){
		
		List<MenuOpciones> menus = null;
		
		try {								
			menus = sqlMap.queryForList("getMenusHijos", menu);					
			
			for (int i = 0; i < menus.size(); i++) {
				MenuOpciones mnu = (MenuOpciones) menus.get(i);
				
				menu.add(mnu);
				
				if(mnu.getHaschildren() != null)
					getMenuHijoAdmin(mnu);					
				
									
		    }
		} catch (SQLException e) {
			e.printStackTrace();
		}			
		
	}
	
	public static Integer getPrivilegioUsuario(Integer user_id){
		Integer privilegio = null;		
        SqlMapClient sqlMap = null;
        
        sqlMap = Conexion.getSqlMap();
		try {
			privilegio = (Integer)sqlMap.queryForObject("getPrivilegio", user_id);				
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return privilegio;
	}
}